/**
 * Coze API 后端代理服务示例
 * 
 * 本示例使用 Express 框架创建一个安全的后端代理，用于转发前端请求到 Coze API
 * 这样可以保护敏感信息如访问令牌，并解决 CORS 问题
 */

const express = require('express');
const cors = require('cors');
const axios = require('axios');
const bodyParser = require('body-parser');
const rateLimit = require('express-rate-limit');

// 创建 Express 应用
const app = express();

// 应用中间件
app.use(cors({
  origin: 'http://your-frontend-domain.com', // 替换为你的前端域名
  methods: ['GET', 'POST'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));
app.use(bodyParser.json({ limit: '15mb' }));

// 限流设置（防止滥用）
const apiLimiter = rateLimit({
  windowMs: 60 * 1000, // 1分钟内
  max: 20, // 每个IP最多20个请求
  message: { error: '请求频率过高，请稍后再试' }
});

// Coze API 的配置信息（建议使用环境变量存储敏感信息）
const COZE_API_URL = 'https://api.coze.cn/v3/chat';
const COZE_AUTH_TOKEN = 'pat_s65ntx3AzCHQnX0xlOr0H8CXW44y5OjybZp6yUzuUnSDTTeol9IvxC6JtMrihfVV';

// 输入验证中间件
function validateInput(req, res, next) {
  const { bot_id, user_id, additional_messages } = req.body;
  
  // 检查必须字段
  if (!bot_id || !user_id || !additional_messages || !additional_messages.length) {
    return res.status(400).json({ error: '缺少必要参数' });
  }
  
  try {
    // 验证 content 是否为有效的 JSON 字符串
    if (additional_messages[0].content) {
      const data = JSON.parse(additional_messages[0].content);
      
      // 验证必须字段
      if (!data.task_id || !data.user_info) {
        return res.status(400).json({ error: 'content 中缺少必要参数' });
      }
      
      // 验证 user_info 字段
      const { birthdate, gender, travel_date, travel_time, location } = data.user_info;
      if (!birthdate || !gender || !travel_date || !travel_time || !location) {
        return res.status(400).json({ error: 'user_info 中缺少必要参数' });
      }
    }
    
    next();
  } catch (error) {
    return res.status(400).json({ error: 'content 不是有效的 JSON 字符串' });
  }
}

// 记录请求日志中间件
function logRequest(req, res, next) {
  console.log(`[${new Date().toISOString()}] 请求: ${JSON.stringify({
    ip: req.ip,
    method: req.method,
    url: req.originalUrl,
    body: {
      ...req.body,
      // 脱敏处理，不记录敏感信息
      additional_messages: req.body.additional_messages ? '[已脱敏]' : undefined
    }
  })}`);
  next();
}

// API 代理端点
app.post('/api/coze', apiLimiter, logRequest, validateInput, async (req, res) => {
  try {
    // 准备请求 Coze API
    const response = await axios({
      method: 'post',
      url: COZE_API_URL,
      headers: {
        'Authorization': `Bearer ${COZE_AUTH_TOKEN}`,
        'Content-Type': 'application/json'
      },
      data: req.body,
      timeout: 30000 // 30秒超时
    });
    
    // 返回 Coze API 的响应
    return res.status(response.status).json(response.data);
  } catch (error) {
    console.error('Coze API 请求失败:', error.message);
    
    // 构造错误响应
    const statusCode = error.response ? error.response.status : 500;
    const errorMessage = error.response && error.response.data 
      ? error.response.data 
      : { error: '服务器内部错误' };
    
    return res.status(statusCode).json(errorMessage);
  }
});

// 健康检查端点
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok' });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Coze API 代理服务已启动，监听端口: ${PORT}`);
});

// 优雅关闭
['SIGINT', 'SIGTERM'].forEach(signal => {
  process.on(signal, () => {
    console.log(`收到 ${signal} 信号，正在关闭服务器...`);
    process.exit(0);
  });
});

/**
 * 使用方法:
 * 1. 安装依赖: npm install express cors axios body-parser express-rate-limit
 * 2. 启动服务器: node coze-api-backend-example.js
 * 3. 前端请求示例:
 *    fetch('http://localhost:3000/api/coze', {
 *      method: 'POST',
 *      headers: { 'Content-Type': 'application/json' },
 *      body: JSON.stringify({
 *        bot_id: "7488929898816798757",
 *        user_id: "user_123",
 *        stream: false,
 *        auto_save_history: true,
 *        additional_messages: [{
 *          role: "user",
 *          content_type: "text",
 *          content: JSON.stringify({
 *            task_id: "task_123",
 *            user_info: {
 *              birthdate: "1995-05-20",
 *              gender: "female",
 *              travel_date: "2023-08-15",
 *              travel_time: "10:00",
 *              location: "杭州西湖",
 *              emotion: "平静"
 *            }
 *          })
 *        }]
 *      })
 *    })
 */ 